(ns com.jeff.tracer.tracer)

(use 'com.jeff.tracer.vect)
(use 'com.jeff.tracer.quadratic)

(def distance
  (fn [p1 p2]
    (let [dx (- (nth p1 0) (nth p2 0))
          dy (- (nth p1 1) (nth p2 1))
          dz (- (nth p1 2) (nth p2 2))]
      (Math/sqrt (+ (* dx dx) (* dy dy) (* dz dz))))))

(def closest
  (fn [origin points]
    (reduce #(if (< (distance origin %1) (distance origin %2)) %1 %2) (first points) points)))

(def make-point
  (fn [ray t]
    (vadd (:origin ray) (vmul (:dir ray) t))))

(def intersect-sphere
  (fn [ray sphere]
    (let [d (vsub (:origin ray) (:center sphere))
          a (dot-prod (:dir ray) (:dir ray))
          b (dot-prod (vmul (:dir ray) 2) d)
          c (- (dot-prod d d) (* (:radius sphere) (:radius sphere)))
          q (quadratic a b c)]
      (closest (:origin ray) (map #(make-point ray %1) q))))) 

(defmulti intersect (fn [ray shape] (:is-a shape)))
(defmethod intersect 'SPHERE [ray shape] (intersect-sphere ray shape))